<?php

    /**
     *
     * Melative Tools singleton
     *
    */

    class MelativeToolsIO
	{
        private static $inst;

        public static function getInstance()
        {
            if( is_null(self::$inst) )
                self::$inst = new MelativeToolsIO();

            return self::$inst;
        }

	    public function curl( $resource, $method="get", $fields=null, $auth=false )
        {
            if( strcasecmp($method,"get")==0 && is_array($fields) )
            {
                $resource .= "?";
                foreach( $fields as $k=>$v )
                    $resource .= $k ."=". urlencode($v) ."&";
            }

            $csess = curl_init( $resource );

            curl_setopt( $csess, CURLOPT_HEADER, 0 );
            curl_setopt( $csess, CURLOPT_RETURNTRANSFER, 1 );

            if( $auth )
            {
                curl_setopt( $csess, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
                curl_setopt( $csess, CURLOPT_USERPWD, "{$auth}");
            }

            if( strcasecmp($method,"post")==0 )
            {
                curl_setopt( $csess, CURLOPT_POST, 1 );
                curl_setopt( $csess, CURLOPT_POSTFIELDS, $fields );
            }

            $resp = curl_exec( $csess );

            curl_close( $csess );

            return $resp;
        }
	}

    class MelativeToolsCache
    {
        private static $inst;

        public static function getInstance()
        {
            if( is_null(self::$inst) )
                self::$inst = new MelativeToolsCache();

            return self::$inst;
        }

        private function key( $resource )
        {
            $k0 = hash( "md5", $resource );
            $k1 = substr( $k0, 0, 2 );
            $k2 = substr( $k0, 2, 2 );
            return (object) array("path"=>"{$k1}/{$k2}/", "hash"=>"{$k0}");
        }

        //
        // isCached: privately check if resource exists or has not expired
        //
        private function isCached( $resource, $lifetime=false, $prefix_dir=false )
        {

            // allow custom management of caching
            if( $this->events->isObserved( 'nu_cache_check' ) )
            {
                $source = (object) array("resource"=>$resource, "lifetime"=>$lifetime);
                $cached = false;
                return $this->events->filter( 'nu_cache_check', $cached, $source );
            }

            if( $this->on )
            {
                $expires    = $this->time - ($lifetime === false ? -100000 : $lifetime);
                $key_path   = $this->key( $resource );
                $key_file   = ( $prefix_dir ? $prefix_dir : $this->cache_dir ) . $key_path->path . $key_path->hash;

                if( file_exists( $key_file ) && filemtime( $key_file ) >= $expires )
                {
                    return true;
                }
            }

            return false;
        }

        //
        // privately cache
        //
        private function _set( $resource, $data, $prefix_dir=false )
        {

            // allow custom management of caching
            if( $this->events->isObserved( 'nu_cache_set' ) )
            {
                $this->events->emit( 'nu_cache_set', $data, $resource );
                return;
            }

            if( $this->on )
            {
                $key_path   = $this->key( $resource );
                $dir        = ($prefix_dir ? $prefix_dir : $this->cache_dir) . $key_path->path;
                $t          = "{$dir}{$key_path->hash}.". microtime(true);

                $this->io->mkdir( "{$dir}" );
                file_put_contents( $t, $data );
                rename( $t, "{$dir}{$key_path->hash}" );
            }
        }

        private static function _get( $resource, $lifetime=false, $prefix_dir=false )
        {

            // allow custom management of caching
            if( $this->events->isObserved( 'nu_cache_get' ) )
            {
                $source = (object) array("resource"=>$resource, "lifetime"=>$lifetime);
                $data = null;
                $data = $this->events->filter( 'nu_cache_get', $data, $source );
                return $data;
            }

            $dir = $prefix_dir ? $prefix_dir : $this->cache_dir;

            if( $this->isCached( $resource, $lifetime, $prefix_dir ) )
            {
                if( ($data = file_get_contents( $resource )) )
                {
                    return $data;
                }
            }

            return false;
        }
    }

    class MelativeTools
    {
        const $domain   = 'http://melative.com/api/';
        const $plugin   = WP_PLUGIN_DIR . '/melative-tools/';

        private static $inst;

        private $io;

        function __construct()
        {
            $this->io = MelativeToolsIO::getInstance();
        }

        public static function getInstance()
        {
            if( is_null(self::$inst) )
                self::$inst = new MelativeTools();

            return self::$inst;
        }
    }

?>